package com.onefish.toolkit.controller;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("api")
public class ZIPController {
    @GetMapping("/downloadZip")
    public void downloadZip(HttpServletResponse response) {
        WritableByteChannel outChannel = null;
        try {
//            response.setContentType("application/octet-stream");
//            response.setHeader("Content-Disposition", "attachment;fileName=" +
//                    new String("文件.zip".getBytes("gbk"), "iso8859-1"));
//            ServletOutputStream os = response.getOutputStream();
//            ZipOutputStream zos = new ZipOutputStream(os);
//            //  服务器本地待下载的文件夹绝对路径
//            String sourceDirPath = "C:\\Users\\Administrator\\Desktop\\test";
//            Path  sourcePath = Paths.get(sourceDirPath);
//            Map<String,Boolean> fileMaps = new HashMap<>();
//            recusiveFolder(sourceDirPath,fileMaps);
//            for (Map.Entry<String, Boolean> entry : fileMaps.entrySet()){
//                String fileAbsolutePath = entry.getKey();
//                boolean isFolder = entry.getValue();
//                if (StringUtils.isBlank(fileAbsolutePath)){
//                    System.out.println("当前文件或文件夹绝对路径为空");
//                    continue;
//                }
//                Path currentPath = Paths.get(fileAbsolutePath);
//                String relativePath = String.valueOf(sourcePath.relativize(currentPath));
//                if (StringUtils.isBlank(relativePath)){
//                    System.out.println("当前文件或文件夹相对路径为空");
//                    continue;
//                }
//                if(isFolder){
//                    zos.putNextEntry(new ZipEntry(relativePath + "/"));
//                } else {
//                    zos.putNextEntry(new ZipEntry(relativePath));
//                    FileInputStream fis = new FileInputStream(fileAbsolutePath);
//                    FileChannel inChannel = fis.getChannel();
//                    outChannel = Channels.newChannel(zos);
//                    long size = inChannel.size();
//                    long position = 0;
//                    long total = 0;
//                    while(position < size){
//                        long currentSize = inChannel.size();
//                        long copySize = inChannel.transferTo(position,currentSize,outChannel);
//                        System.out.println("当次拷贝字节数: " + copySize + "  当次拷贝索引位置: " + position + " 剩余字节数: " + (currentSize-copySize));
//                        if (copySize <= 0){
//                            System.out.println("当次拷贝字节数为空，退出");
//                            break;
//                        }
//                        position += copySize;
//                        total += copySize;
//                    }
//                    System.out.println("拷贝总字节数：" + total);
//                    zos.flush();
//                    inChannel.close();
//                }
//            }
//            zos.closeEntry();
//            zos.close();
//            outChannel.close();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" +
                    new String("文件.zip".getBytes("gbk"), "iso8859-1"));
            ServletOutputStream os = response.getOutputStream();
            ZipOutputStream zos = new ZipOutputStream(os);

            byte[] buf = new byte[1024 * 2];
//            for (int i = 1; i < 4; i++) {
//                String name = "a/b/c/";
//                zos.putNextEntry(new ZipEntry(name + i + ".txt"));
//                FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\c\\" + i + ".txt");
//                //使用字节缓冲输入流
//                BufferedInputStream bis = new BufferedInputStream(fis);
//                int len;
//                while ((len = bis.read(buf)) != -1) {
//                    zos.write(buf, 0, len);
//                }
//                zos.closeEntry();
//                bis.close();
//            }
            // 空文件夹的处理, 最后不加 / 会将c当成文件处理
            zos.putNextEntry(new ZipEntry("a/d" + "/"));
            // 没有文件，不需要文件的copy
            zos.closeEntry();
            //必须要执行 zos.finish(); close()时内部会调用finish()
            zos.close();

        } catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void recusiveFolder(String folderPath, Map<String, Boolean> absolutePath){
        try {
            Path directoryPath = Paths.get(folderPath);
            DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directoryPath);
            for (Path path : directoryStream) {
                if (Files.isDirectory(path)) {
                    absolutePath.put(String.valueOf(path.toAbsolutePath()),true);
                    System.out.println("文件夹：" + path.toAbsolutePath() +  " 当前层级:" + path.getNameCount());
                    recusiveFolder(String.valueOf(path.toAbsolutePath()),absolutePath);
                } else {
                    absolutePath.put(String.valueOf(path.toAbsolutePath()),false);
                    System.out.println("文件：" + path.toAbsolutePath() +  " 当前层级:" + (path.getNameCount()-1));
                }
            }
            directoryStream.close();
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    //递归文件夹
    public static void recursiveFolder(File folder, WritableByteChannel outChannel) {
        try {
            File[] files = folder.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    // 如果是子文件夹，递归遍历
                    recursiveFolder(file, outChannel);
                } else {
                    // 如果是文件，传输文件内容到输出流
                    transferFile(file, outChannel);
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    //传输文件
    public static void transferFile(File file, WritableByteChannel outChannel){
        try (FileChannel inChannel = new FileInputStream(file).getChannel())
        {
            long size = inChannel.size();
            long position = 0;
            long total = 0;
            while(position < size){
                long currentSize = inChannel.size();
                // 使用零拷贝方式将文件内容传输到输出流
                long copySize = inChannel.transferTo(position,currentSize,outChannel);
                System.out.println("当次拷贝字节数: " + copySize + "  当次拷贝索引位置: " + position + " 剩余字节数: " + (currentSize-copySize));
                if (copySize <= 0){
                    System.out.println("当次拷贝字节数为空，退出");
                    break;
                }
                position += copySize;
                total += copySize;
            }

            System.out.println("拷贝总字节数：" + total);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
